package com.ohuang.demo.webView

import android.os.SystemClock
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.webkit.WebViewClient
import com.ohuang.demo.http.testApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.Request
import okhttp3.Response
import org.json.JSONObject
import java.io.ByteArrayInputStream
import java.io.IOException
import java.io.InputStream
import java.nio.charset.StandardCharsets
import kotlin.coroutines.resume


class SteamDbWebView {

    data class WebClickPosition(
        var x: Float = 0f, var y: Float = 0f
    )

    private var mWebView: WebView? = null
    private val TAG = "SteamDbWebView"
    var mainScope = MainScope()
    var isClickRealHuman = false
    var mJob: Job? = null
    var mWebClickPosition: WebClickPosition? = null

    private var mWebViewClient = object : WebViewClient() {

        override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
            Log.d(TAG, "shouldOverrideUrlLoading: url=$url")
            return super.shouldOverrideUrlLoading(view, url)
        }

        override fun onPageFinished(view: WebView?, url: String?) {
            super.onPageFinished(view, url)
            Log.d(TAG, "onPageFinished: $url")
            if (url != null && url.startsWith("https://steamdb.info/app")) {
                mJob?.cancel()

                mJob = mainScope.launch {
                    var count = 10
                    while (count > 0) {
                        delay(3000)
                        count--
                        findRealHuman()
                    }

                }
            }
        }

        override fun shouldInterceptRequest(
            view: WebView?,
            request: WebResourceRequest?
        ): WebResourceResponse? {
            if (request == null || isClickRealHuman) {
                return null
            }
//            if (request.url.toString()
//                    .endsWith(".html") || request.url.toString()
//                    .endsWith("/")
//            ) {
//                return WebResourceResponse(
//                    "text/html",
//                    "UTF-8",
//                    getInputStreamWithInjectedScript(request)
//                )
//            }
            return super.shouldInterceptRequest(view, request)
        }

    }

    private fun getInputStreamWithInjectedScript(request: WebResourceRequest): InputStream? {
        try {
            // 获取原始的 HTML 内容
            val mBuilder =
                Request.Builder().url(request.url.toString()).method(request.method, null)
            val requestHeaders = request.requestHeaders
            requestHeaders.entries.forEach {
                mBuilder.addHeader(it.key, it.value)
            }
            val mResponse: Response = testApi.mOkHttpClient.newCall(mBuilder.build()).execute()
            Log.d(
                TAG,
                "getInputStreamWithInjectedScript: code=${mResponse.code} msg=${mResponse.message}"
            )
            val originalHtml = mResponse.body?.string()
            if (originalHtml == null) {
                return null
            }

            // 注入自定义的 JavaScript 代码
            val injectedScript = ("<script type='text/javascript'>"
                    + "let oldAttachShadow = Element.prototype.attachShadow;"
                    + "Element.prototype.attachShadow = function(...args) {"
                    + "    console.log('attach劫持', ...args);"
                    + "    args[0].mode = 'open';"
                    + "    return oldAttachShadow.call(this, ...args);"
                    + "};"
                    + "</script>")

            // 将注入的脚本添加到 HTML 的 <head> 部分
            val modifiedHtml = originalHtml.replaceFirst(
                "<head>".toRegex(),
                "<head>$injectedScript"
            )

            // 返回修改后的 HTML 内容
            return ByteArrayInputStream(modifiedHtml.toByteArray(StandardCharsets.UTF_8))
        } catch (e: IOException) {
            e.printStackTrace()
            return null
        }
    }

    private var mWebChromeClient = object : WebChromeClient() {


    }

    fun initWebView(webView: WebView) {
        mWebView = webView
        webView.defaultSetting()
        webView.webViewClient = mWebViewClient
        webView.webChromeClient = mWebChromeClient
    }


    private var call: (String) -> Unit = { _ -> }

    suspend fun loadUrlInfo(url: String): String {
        return suspendCancellableCoroutine { cancellableContinuation ->
            loadUrlInfo(url) {
                if (cancellableContinuation.isActive) {
                    cancellableContinuation.resume(it)
                }
            }
        }
    }

    /**
     * 模拟点击
     */
    private suspend fun findRealHuman(): Boolean {
        return suspendCancellableCoroutine { cancellableContinuation ->
            mWebView?.evaluateJavascript(
                """
                var ifr = document.querySelector(".main-content > div > div > div")
                var rect = ifr.getBoundingClientRect();

                console.log({
                  top: rect.top,     // 元素顶部到视口顶部的距离
                  right: rect.right, // 元素右侧到视口左侧的距离
                  bottom: rect.bottom, // 元素底部到视口顶部的距离
                  left: rect.left,   // 元素左侧到视口左侧的距离
                  width: rect.width,
                  height: rect.height
                });
                var x=rect.left + 25
                var y=(rect.bottom - rect.top)/2 + rect.top
                var width = window.innerWidth;
                var height = window.innerHeight;
                x+","+y+","+width
            """.trimIndent(),
                ValueCallback<String> { value ->
                    val newValue = value.replace("\"", "")
                    Log.d(TAG, "clickRealHuman: $value")
                    val split = newValue.split(",")
                    try {
                        val x = split[0].toFloat()
                        val y = split[1].toFloat()
                        val width = split[2].toFloat()  // 网页的宽度
                        val webViewRealWidth = mWebView?.width?.toFloat() ?: 0F  //webView的宽度
                        val isGetPosition =
                            x != 0f && y != 0f && width != 0f && webViewRealWidth != 0f
                        Log.d(TAG, "findRealHuman: x=$x y=$y width=$width")
                        if (isGetPosition) {
                            val a = webViewRealWidth / width  //计算系数
                            isClickRealHuman = true
                            mWebClickPosition = WebClickPosition(x * a, y * a)
                            if (mWebView != null) {
                                performTouchEventClick(
                                    mWebView!!,
                                    mWebClickPosition!!.x,
                                    mWebClickPosition!!.y
                                )
                            }
                        }
                        if (cancellableContinuation.isActive) {
                            cancellableContinuation.resume(isGetPosition)
                        }

                    } catch (e: Exception) {

                        if (cancellableContinuation.isActive) {
                            cancellableContinuation.resume(false)
                        }
                    }

                })
        }

    }

    private fun performTouchEventClick(view: View, x: Float, y: Float) {
        var downTime = SystemClock.uptimeMillis()
        val downEvent = MotionEvent.obtain(
            downTime, downTime,
            MotionEvent.ACTION_DOWN,
            x, y, 0
        )
        downTime += 200
        val upEvent = MotionEvent.obtain(
            downTime, downTime,
            MotionEvent.ACTION_UP,
            x, y, 0
        )
        view.dispatchTouchEvent(downEvent)
        view.dispatchTouchEvent(upEvent)
        downEvent.recycle()
        upEvent.recycle()
    }

    private fun loadUrlInfo(url: String, call: (String) -> Unit) {
        mWebView!!.loadUrl(url)
        this.call = call
    }

    private suspend fun getHtml(): String {
        return suspendCancellableCoroutine<String> { cancellableContinuation ->

            mWebView?.evaluateJavascript("(function() { var html = document.documentElement.outerHTML; return html; })();",
                ValueCallback<String> { json ->
                    // 这里获取到的html包含转义字符，需要处理
                    val html = JSONObject("{\"html\":$json}").getString("html")
                    if (cancellableContinuation.isActive) {
                        cancellableContinuation.resume(html)
                    }
                    // 使用获取到的HTML内容
                })
        }

    }


    fun onDestroy() {
        mWebView = null
        mainScope.cancel()
    }


}